// 全局公共方法
// 此处第二个参数vm，也就是页面使用的this


import $routes from '@/libs/routes/index.js'

const install = (Vue, vm) => {
	

	// 校验是否是H5页面
	const checkH5 = (url) => {
		const testHttp = vm.$u.test.url(url)
		if (testHttp) {
			return '/pages/h5/h5?url=' + url
		} else {
			return url
		}
	}
	// URL参数转对象
	const paramsToObj = (url) => {
	    let arr = ''
		// 如果是完整URL，包含?号，先通过?号分解
		if (url.indexOf('?') != -1) {
			 arr = url.split('?')[1]
		}
		 arr = arr.split('&') //先通过？分解得到？后面的所需字符串，再将其通过&分解开存放在数组里
		let obj = {}
		for (let i of arr) {
			obj[i.split('=')[0]] = i.split('=')[1] //对数组每项用=分解开，=前为对象属性名，=后为属性值
		}
		return obj
	}

	// 刷新当前页面
	const refreshPage = () => {
		const pages = getCurrentPages()
		const currentPage = pages[pages.length - 1]
		const path = '/' + currentPage.route + vm.$u.queryParams(currentPage.options)
		if (vm.$u.test.contains(currentPage.route, 'tabbar')) {
			uni.reLaunch({
				url: path,
				fail: (err) => {
					console.log(err)
				}
			})
		} else {
			uni.redirectTo({
				url: path,
				fail: (err) => {
					console.log(err)
				}
			})
		}
	}

	// toast
	const showToast = (data = {}) => {
		if (typeof data == 'string') {
			uni.showToast({
				title: data,
				icon: 'none'
			})
		} else {
			uni.showToast({
				title: data.title,
				icon: data.icon || 'none',
				image: data.image || '',
				mask: data.mask || false,
				position: data.position || 'center',
				duration: data.duration || 1500,
				success: () => {
					setTimeout(() => {
						if (data.back) return uni.navigateBack()
						data.success && data.success()
					}, data.duration || 1500)
				}
			})
		}
	}

	// 单图上传
	const uploadImage = (callback) => {
		uni.chooseImage({
			count: 1,
			success: img => {
				const tempFilePaths = img.tempFilePaths
				uni.uploadFile({
					url: 'xxx.com',
					filePath: tempFilePaths[0],
					name: 'file',
					header: {
						openid: vm.userInfo.openid || ''
					},
					success: res => {
						callback && callback(JSON.parse(res.data))
					}
				})
			}
		})
	}
	
	// 小程序支付
	const wxappPay = ({
		payInfo,
		success,
		fail,
		complete
	}) => {
		uni.requestPayment({
			provider: 'wxpay',
			timeStamp: payInfo.timeStamp + '',
			nonceStr: payInfo.nonceStr,
			package: payInfo.package,
			paySign: payInfo.paySign,
			signType: payInfo.signType,
			success: res => {
				success && success(res)
			},
			fail: err => {
				fail && fail(err)
			},
			complete: res => {
				complete && complete(res)
			}
		})
	}
	
	
	
	/**
	 * 自动根据字符串路径获取对象中的值支持.和[] , 且任意一个值为undefined时,不会报错,会直接返回undefined
	 * @param	{Object} proto 数据源
	 * @param	{String} name 支持a.b 和 a[b]
	 * @param	{String} defaultValue undefined时的默认值
	 */
	const getObjData = function(proto, name, defaultValue) {
		let newDataObj;
		if (isNotNull(proto)) {
			// newDataObj = JSON.parse(JSON.stringify(proto));
			newDataObj = proto;
			let k = "",
				d = ".",
				l = "[",
				r = "]";
			name = name.replace(/\s+/g, k) + d;
			let tstr = k;
			for (let i = 0; i < name.length; i++) {
				let theChar = name.charAt(i);
				if (theChar != d && theChar != l && theChar != r) {
					tstr += theChar;
				} else if (newDataObj) {
					if (tstr != k) newDataObj = newDataObj[tstr];
					tstr = k;
				}
			}
		}
		if (typeof newDataObj === "undefined" && isNotNull(defaultValue)) newDataObj = defaultValue;
		return newDataObj;
	};

	/**
	 * 检测参数是否不为空 结果与 isNull 相反
	 */
	const isNotNull = function(value) {
		return !isNull(value);
	};
	
	/**
	 * 检测参数是否为空 其中 undefined、null、{}、[]、"" 均为空值  true 空值  false 有值
	 */
	const isNull = function(value) {
		let key = false;
		if (
			typeof value == "undefined" ||
			Object.prototype.toString.call(value) == "[object Null]" ||
			JSON.stringify(value) == "{}" ||
			JSON.stringify(value) == "[]" ||
			value === "" ||
			JSON.stringify(value) === undefined
		) {
			key = true;
		}
		return key;
	};
	
	/**
	 * 判断是否是 undefined
	 * @param {Object} val
	 */
	const isUndefined = function(val) {
	    return typeof val === 'undefined'
	}
	
	/**
	 * 检测是否是完整的web链接，即是否带有http
	 * @param {Object} str
	 */
	const isFullWebLink = function(str){
		// var pattern = /(https?:\/\/)/g;
        // 有很多种的协议类型，所以直接判断://
		var pattern = /:\/\//;
		return pattern.test(str)
	}
	
	/**
	 * 判断登录操作
	 * @param {Object} task
	 * @param {Object} tips
	 */
	const hasLoginTask = function(task, tips = '您需要登录后才能继续操作'){
		if(uni.$u.vuex.getters('hasLogin')){
			task && task()
		}else {
			uni.showModal({
				title: '提示',
				content: tips,
				success: function (res) {
					if (res.confirm) {
						exitLoginPageProcessing(true)
					} else if (res.cancel) {
						exitLoginPageProcessing(false)
					}
				}
			})
		}
	}
	
	/**
	 * 退出登录处理
	 * @@param routeLogin  跳转登录页面
	 */
	function exitLoginPageProcessing(routeLogin = false){
		uni.$u.vuex.dispatch('user/exitLogin')
		let pages = getCurrentPages();
	
		let currentRoute = '/' + pages[pages.length - 1].route; //  /pages/index/index
		 
		// 不去登录页则判断当前页面是不是需要登录的页面，如果需要登录，则返回至不需要登录的页面，否则去重定向页面
		if($routes[currentRoute]?.requiresAuth || false){
			let i = pages.length - 1
			
			// 查找返回至页面路由栈不需要登录的页面的返回数量
			for(i;i >= 0; i--){
				let p = pages[i]
				if(!$routes[ '/' + p.route ] || !$routes[ '/' + p.route ].requiresAuth){
					break
				}
			}
			
			let backIndex = pages.length - 1 - i
			uni.navigateBack({
				delta: backIndex,
				complete() {
					// 返回至不需要登录的页面后再 跳转登录页面
					if(routeLogin){
						let loginPage = uni.$u.$config.loginPage;
						if (currentRoute == loginPage) return
						uni.navigateTo({
							url: loginPage
						})
					}
				}
			})
		}else {
			// 返回至不需要登录的页面后再 跳转登录页面
			if(routeLogin){
				let loginPage = uni.$u.$config.loginPage;
				if (currentRoute == loginPage) return
				uni.navigateTo({
					url: loginPage
				})
			}
		}
	}
    
    /**
     * 根据路由地址查找页面
     * @param {Object} findRoute
     */
    const findPages = function(findRoute){
        let pages = getCurrentPages()
        return pages.find(page => '/' + page.route === findRoute)
    }
	
    /**
     * 打开外部链接
     * @param {Object} url
     */
    const openlinks = function (url){
        // #ifdef MP-WEIXIN
        uni.navigateTo({
            url: '/pages/web-view/web-view?encodeUrl=' + encodeURIComponent(url)
        })
        // #endif
        // #ifdef H5
        window.open(url)
        // #endif
        // #ifdef APP-PLUS
        plus.webview.open(url)
        // #endif
    }
    /**
     * 订阅消息
     * @param {Object} tmplIds
     * @param {Object} successFn
     */
    const requestSubscribeMessage = function(tmplIds, successFn){
        // #ifdef MP-WEIXIN
        uni.getSetting({
            withSubscriptions: true, // 需要设置 withSubscriptions 为 true
            success(res) {
                // 查看是否有没通过权限的订阅消息，如有则请求
                const notTmplIds = tmplIds.filter(id => !res.subscriptionsSetting[id] || res.subscriptionsSetting[id] !== 'accept')
                if(notTmplIds.length){
                    // 获取未通过订阅权限
                    wx.requestSubscribeMessage({
                        tmplIds: notTmplIds, // 替换为您的订阅消息模板 ID
                        success: (res) => {
                          // if (res['yourTemplateID1'] === 'accept' && res['yourTemplateID2'] === 'accept') {
                          //   // 用户同意订阅消息，可以在这里执行后续操作
                          // }
                            successFn && successFn(res)
                        },
                        fail: (errors) => {
                            console.log(errors)
                        }
                    })
                }
                
            }
        })
        // #endif
    }
    
    // const openNavigation = function({ lng,  }){
    //     https://uri.amap.com/navigation?from=当前位置&to=目的地&mode=car&policy=1&src=yourAppName
    // }
    
    /**
     * uni图片预览
     * @param {Object} current
     * @param {Object} urls
     */
    const previewImage = function(current, urls){
        uni.previewImage({
            current,
            urls
        })
    }
    
    /**
     * 清除对象空属性，只返回有值 的属性
     * @param {Object} obj
     */
    const removeEmptyAttr = function(obj){
        let newObj = {}
        Object.keys(obj).forEach(key => {
            if(isNotNull(obj[key])) newObj[key] = obj[key]
        })
        return newObj
    }
    
    /**
     * 拨打电话
     * @param {Object} phoneNumber 电话号码
     */
    const makePhoneCall = function(phoneNumber){
        uni.makePhoneCall({ phoneNumber })
    }
    
    /**
     * 只合并对象本身属性值
     * @param {Object} protoObj
     * @param {Object} mergeDataObj
     */
    const mergeObjAttributeValues = function(protoObj, mergeDataObj){
        const uploadKeys = Object.keys(protoObj)
        uploadKeys.forEach((prop) => {
            if (isNotNull(mergeDataObj[prop])) {
                protoObj[prop] = mergeDataObj[prop]
            }
        })
        return protoObj
    }
    
    /**
     * 映射数组label
     * @param {Object} value
     * @param {Object} array
     * @param {Object} valueKey
     * @param {Object} labelKey
     */
    const mapArrayLabel = function(value, array, valueKey = 'id', labelKey = 'label'){
        let item = array.find(e => e[valueKey] == value)
        return item ? item[labelKey] : ''
    }
    
    /**
     * 过滤条件数组
     */
    const filterValueInArray = function(values, array, valueKey = 'id'){
        return array.filter(e => values.includes(e[valueKey]))
    }
    
    /**
     * 环境执行
     */
    
    /**
     * 判断function
     * @param {Function} fn
     */
    function isFunc(fn){
        return typeof fn === 'function'
    }
    
    /**
     * h5环境执行，使用场景：h5项目判断是在哪个环境(微信小程序、微信浏览器、ios应用内、android应用内)下运行，做出不同的处理逻辑
     */
    const h5evn = function({
        // 微信小程序
        mpWeixin,
        // 微信浏览器
        webWeixin,
        // ios app
        iosApp,
        // android app
        androidApp,
        // h5
        h5
    }){
        var ua = window.navigator.userAgent.toLowerCase()
        // 小程序
        if (window.__wxjs_environment === 'miniprogram') {
            isFunc(mpWeixin) && mpWeixin()
        // 微信浏览器环境
        } else if(ua.match(/micromessenger/i) == 'micromessenger'){
            isFunc(webWeixin) && webWeixin()
        // 海螺
        }else {
            // 暂时没有方法app内嵌判断，通过异常判断
            try{
                var platform = uni.getSystemInfoSync().platform
                // ios
                if(platform == 'ios'){
                    // 在这里如果不是ios web-view 通常就会抛出异常
                    if(window.webkit.messageHandlers){
                        isFunc(iosApp) && iosApp()
                    }else {
                        isFunc(h5) && h5()
                    }
                // 安卓
                }else if(platform == 'android' && window.android){
                    isFunc(androidApp) && androidApp()
                }else {
                    isFunc(h5) && h5()
                }
            }catch(e){
                isFunc(h5) && h5()
            }
        }
    }
    
	// 将各个定义的方法，统一放进对象挂载到vm.$u.func(因为vm就是this，也即this.$u.func)下
	Vue.prototype.$u.func = {
		checkH5,
		paramsToObj,
		refreshPage,
		showToast,
		uploadImage,
		wxappPay,
		getObjData,
		isNotNull,
		isNull,
		isUndefined,
		isFullWebLink,
		hasLoginTask,
        findPages,
        openlinks,
        requestSubscribeMessage,
        previewImage,
        removeEmptyAttr,
        makePhoneCall, 
        mergeObjAttributeValues,
        mapArrayLabel,
        filterValueInArray,
        h5evn,
        isFunc
	}
}
export default {
	install
}
